home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / graphics / gifmach3 / part02 < prev    next >
Encoding:
Internet Message Format  |  1991-08-31  |  33.8 KB

  1. Path: news.larc.nasa.gov!amiga-request
  2. From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
  3. Subject: v91i166: GIFMachine 2.137 - convert GIF images into IFF SHAMs, Part02/03
  4. Reply-To: caw@miroc.chi.il.us (Christopher A. Wichura)
  5. Newsgroups: comp.sources.amiga
  6. Message-ID: <comp.sources.amiga.v91i166@ab20.larc.nasa.gov>
  7. References: <comp.sources.amiga.v91i165@ab20.larc.nasa.gov>
  8. Date: 31 Aug 91 10:10:20 GMT
  9. Approved: tadguy@uunet.UU.NET (Tad Guy)
  10. X-Mail-Submissions-To: amiga@uunet.uu.net
  11. X-Post-Discussions-To: comp.sys.amiga.misc
  12.  
  13. Submitted-by: caw@miroc.chi.il.us (Christopher A. Wichura)
  14. Posting-number: Volume 91, Issue 166
  15. Archive-name: graphics/gifmachine2137/part02
  16.  
  17. #!/bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 2 (of 3)."
  24. # Contents:  GIFMachine.docs Sources/main.c Sources/writeiff.c
  25. # Wrapped by tadguy@ab20 on Wed Aug 28 21:46:33 1991
  26. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  27. if test -f 'GIFMachine.docs' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'GIFMachine.docs'\"
  29. else
  30. echo shar: Extracting \"'GIFMachine.docs'\" \(9120 characters\)
  31. sed "s/^X//" >'GIFMachine.docs' <<'END_OF_FILE'
  32. X
  33. X                                GIFMachine
  34. X
  35. X                 Copyright 1990 by Christopher A. Wichura
  36. X                           (caw@miroc.chi.il.us)
  37. X
  38. X
  39. XLegal mumbo jumbo:
  40. X
  41. XGIFMachine is not in the public domain.  All source files, along with the
  42. Xresulting executable, are copyright by C. Wichura.  You may not sell
  43. XGIFMachine.  The only allowed charge that may be placed on GIFMachine is
  44. Xfor media and/or mailing costs.
  45. X
  46. XGIFMachine may be freely redistributed via BBSs, InterNet/Usenet, and disk
  47. Xlibraries such as Fred Fish's, as long as the archive is not modified.
  48. XDisk magazines and services that charge extra for file transfers may not
  49. Xdistribute GIFMachine.
  50. X
  51. XIn using GIFMachine, you accept the responsibility for any damage or loss of
  52. Xproductivity/money that may occur through or during its use.  C. Wichura is
  53. Xnot and can not be held accountable.
  54. X
  55. X                            What is GIFMachine?
  56. X                            ~~~~~~~~~~~~~~~~~~~
  57. XGIFMachine is a program that converts pictures stored in the CompuServe GIF
  58. X(Graphics Interchange Format) format into IFF SHAM format.  There are very
  59. Xfew programs that do this, and most have many problems (not that GIFMachine
  60. Xdoesn't either -- see below).
  61. X
  62. XFor a long time, I used a program called ShamSharp to convert GIFs to IFF
  63. Xformat.  ShamSharp was the only thing I would even consider using (execpt
  64. Xfor ASDG's The Art Department, a very fine commercial product!).  However,
  65. Xthere were a number of things about it that irked me.
  66. X
  67. X   1)  If a picture had >16 colours and a width >320, ShamSharp would
  68. X       __ALWAYS__ halve the width of the image.  Not only that, but it
  69. X       did so by simply skipping every other pixel of the original GIF.
  70. X       This resulted in a tremendous loss in resolution.
  71. X
  72. X       I, myself, would rather have the entire picture converted and be
  73. X       able to use my favorite viewer (Mostra, by S. Vigna) to scroll
  74. X       around the image.  Thus, by default, GIFMachine will not halve
  75. X       the picture's width.  There is a command line switch to make it
  76. X       do so, however, in which case it actually thinks about it a bit
  77. X       rather than just dropping the odd pixels.
  78. X
  79. X   2)  If an image had more than 400 lines in it, ShamSharp would
  80. X       GURU the system if the SHAM mode flag was used.  GIFMachine handles
  81. X       large pictures well (that was one of the primary concerns I had
  82. X       while writing it) and has been tested with images as large as
  83. X       1152x890!
  84. X
  85. X   3)  ShamSharp would write bad IFF files for me on a regular basis.  I
  86. X       suspect this is because of some subtle bug in the cmpByteRun1
  87. X       compression routine ShamSharp uses.  Anyway, GIFMachine has yet to
  88. X       write a bad IFF on me.  (Cross Fingers, Cross Fingers :-)
  89. X
  90. XGIFMachine also offers the user the ability to automatically remove a
  91. Xborder area in a picture, among its other toys.  (I just hate it when you
  92. Xhave an image floating in the middle of the screen with inches of nothing
  93. Xaround it.)
  94. X
  95. X                          Drawbacks of GIFMachine
  96. X                          ~~~~~~~~~~~~~~~~~~~~~~~
  97. XIf you are looking for speed, go someplace else.  GIFMachine was written
  98. Xwith the idea of getting the best possible image from a GIF file, not as
  99. Xsomething to view GIFs in a quick and dirty manner.  Usually what I do is
  100. Xuse something like HAMGIF to see if the GIF is actually worth the effort
  101. Xand then convert a series of GIFs in one shot by specifying multiple
  102. Xfilepspecs.  On a stock 500, the average picture takes around 25 minutes to
  103. Xconvert (half that if the image is interlaced, which is often the case when
  104. Xthe width is halved).
  105. X
  106. XGIFMachine knows how to write only one thing: SHAMs.  If a picture only
  107. Xuses <= 16 colours, SHAM is not needed.  It would be much faster to write a
  108. Xnormal IFF and skip the SHAM conversion calculations.  In such a case, it
  109. Xwould be better to go back and use something like ShamSharp.  (Note that
  110. Xthis has changed with GIFMachine v2:  You can now write 24bit deep ILBMs as
  111. Xwell.)
  112. X
  113. XThe only viewer I know of that properly handles SHAMs with >400 lines is
  114. XMostra.  SuperSham 3.2 (?) will display the image, but does not allow
  115. Xscrolling around.  The latest version of Christian Weber's ShowIFF
  116. X(included in the v18.? distribution of his iff.library) will also display
  117. XSHAMs and let one scroll around.  However, he does not rebuild the copper
  118. Xlist during vertical scrolling and thus the image turns to muck if one
  119. Xscrolls down.
  120. X
  121. X                             Using GIFMachine
  122. X                             ~~~~~~~~~~~~~~~~
  123. XGIFMachine requires that you have KickStart 2.0 or greater (hey, I have a
  124. X3000 and SAS C with 2.0 includes so I dumped ARP in favor of 2.0).  It also
  125. Xrequires a fair amount of RAM (though it does not have to be CHIP RAM or
  126. Xcontiguous).  Alas, memory requirements have gone up with v2; the primary
  127. Ximage now requires three bytes to store a pixel instead of two.   A 640x480
  128. XGIF now requires about a meg of free memory to convert.
  129. X
  130. XGIFMachine uses the 2.0 ReadArgs() argument parser.  Thus, one can always
  131. Xenter `GIFMachine ?' on the command line for help.  GIFMachine can not be
  132. Xrun from the WorkBench.
  133. X
  134. XGIFMachine accepts the following arguments:
  135. X
  136. X<filespec1> ... <filespecN> [TO <directory or filespec>] [ALL]
  137. X                            [NOBORDER <line thresh>] [XCOMP] [DITHER]
  138. X                            [XFLIP] [YFLIP] [DEEP] [NOCOUNT]
  139. X                            [BUFSIZE <Size in KBytes>]
  140. X
  141. XEach filespec may contain any valid 2.0 wildcards (really regular
  142. Xexpressions).
  143. X
  144. XThe TO option allows one to specify where to put the IFFs.  If not given,
  145. Xthey will be placed in the current directory.  It is generally advised that
  146. XTO point at a directory.  However, if you are converting only a single GIF
  147. Xfile then there is no reason one can not specify a full filespec.
  148. X
  149. XThe ALL option will cause GIFMachine to recursively descend into any
  150. Xdirectories while matching filespecs.
  151. X
  152. XThe NOBORDER option instructs GIFMachine to remove the border area from an
  153. Ximage.  It takes, as its <line thresh> parameter, an integer between 0 and
  154. X100 that indicates what percentage of a line can differ from the border
  155. Xcolour and still have the line removed.  This option has been slightly
  156. Xmodified in the v2 release:  Before, GIFMachine assumed that the value at
  157. Xcoordinate 0,0 was the colour of the entire border area.  This is not
  158. Xalways the case, however.  Take, for example, a GIF with the image right up
  159. Xin the upper left corner with a large empty region to the right and below
  160. Xof it.  Such an image would have almost none of the offending border
  161. Xremoved.  GIFMachine will now attempt to run the stripper four times, using
  162. Xeach of the four corners' colour for the border check.  For the most part,
  163. Xthis does not slow this function down because a border check is aborted as
  164. Xsoon as the <line thresh> is exceeded and GIFMachine moves to the next
  165. Xcorner.
  166. X
  167. XThe next option, XCOMP, tells GIFMachine to halve the width of images.
  168. X
  169. XWhen the DITHER option is specified, a boustrophedonic Floyd-Steinberg
  170. Xerror diffusion algorythm will be used when reducing the colour palette to
  171. X12 bits.  This can help eliminate colour banding that occurs in places
  172. Xwhere subtle shadows occur.
  173. X
  174. XThe XFLIP and YFLIP options will flip the image horizontally and
  175. Xvertically, respectively.
  176. X
  177. XThe DEEP option will cause GIFMachine to write a 24bit deep ILBM instead of
  178. Xa SHAM file.  The DITHER option will be ignored in this mode, however.
  179. XWriting deep ILBMs if much faster than writing SHAMs because no
  180. Xcomputations need to be made.  Please note that files written with this
  181. Xoption in effect can be quite large.  Expect a 640x480 XCOMPed image to be
  182. Xover 400k in length, for example.
  183. X
  184. XThe NOCOUNT option will suppress the printing of line numbers while various
  185. Xoperations are being performed.  This can speed the conversion process up a
  186. Xtad, as GIFMachine does not have to wait on the console to display
  187. Xmessages.
  188. X
  189. XThe final option, BUFSIZE, allows one to change the read buffer size used
  190. Xwhen decompressing GIFs.  It defaults to two Kbytes.  The argument is
  191. Xspecified in number of Kbytes, not bytes.  Thus, if you have memory to burn
  192. Xand want a large buffer you could specify a BUFSIZE 100 and you would get a
  193. Xbuffer 100k in size.  This command does not effect the writing of the IFF
  194. Xfile, however.
  195. X
  196. XNote that if GIFMachine determines that the image can be written interlaced
  197. X(depends on aspect ratios) then it will work on two lines at a time instead
  198. Xof one.  This is because the SHAM format only changes the base colours
  199. Xevery other line when displaying interlaced images.
  200. X
  201. XGIFMachine and GIF89a compatibility:  GIFMachine should be able to read any
  202. XGIF file written under the GIF89a specs.  GIFMachine does not, however,
  203. Xperform aspect corrections or process Plain Text Extensions (for obvious
  204. Xreasons), Graphic Control Extensions, or Application Extensions.
  205. XGIFMachine will, however, detect the new Comment Extension blocks.  The
  206. Xmessages contained in such blocks will be stored and output as ANNO chunks
  207. Xwhen the IFF file is being written.
  208. X
  209. X-=> CAW
  210. X
  211. X                    Christopher A. Wichura
  212. X                    5450 East View Park
  213. X                    Chicago, Il  60615
  214. END_OF_FILE
  215. if test 9120 -ne `wc -c <'GIFMachine.docs'`; then
  216.     echo shar: \"'GIFMachine.docs'\" unpacked with wrong size!
  217. fi
  218. # end of 'GIFMachine.docs'
  219. fi
  220. if test -f 'Sources/main.c' -a "${1}" != "-c" ; then 
  221.   echo shar: Will not clobber existing file \"'Sources/main.c'\"
  222. else
  223. echo shar: Extracting \"'Sources/main.c'\" \(11230 characters\)
  224. sed "s/^X//" >'Sources/main.c' <<'END_OF_FILE'
  225. X/* Copyright 1990 by Christopher A. Wichura.
  226. X   See file GIFMachine.doc for full description of rights.
  227. X*/
  228. X
  229. X#include "GIFMachine.h"
  230. X#include <dos/rdargs.h>
  231. X#include <dos/dosasl.h>
  232. X#include <dos/stdio.h>
  233. X#include <workbench/startup.h>
  234. X
  235. Xstruct GIFdescriptor gdesc;
  236. X
  237. Xstruct RGB **BitPlane;
  238. Xstruct RGB GlobalColourTable[256];
  239. X
  240. Xextern UWORD *SHAMmem;
  241. X
  242. Xextern BYTE *PlaneBuf;
  243. X
  244. Xextern BOOL Laced;
  245. X
  246. Xextern UBYTE *Planes[24];
  247. X
  248. XULONG ImageNumber;
  249. X
  250. Xextern struct MinList CommentList;
  251. X
  252. X/* indicates which memory list to allocate from */
  253. Xextern UWORD CurrentMem;
  254. X
  255. X/* the current GIF file handle */
  256. XBPTR GIFfh = NULL;
  257. X
  258. X/* flag: display line counts during conversion or not */
  259. XBOOL DisplayCounts;
  260. X
  261. X/* here we have some defines relating to our GADS call */
  262. X#define ESC "\x1B["
  263. X#define GIFMACH ESC "1;33;42mGIFMachine" ESC "0;32;40m"
  264. X
  265. X#define ARG_TEMPLATE "GIFfiles/A/M,TO/K,ALL/S,NOBORDER/N/K,XCOMP/S,DITHER/S,XFLIP/S,YFLIP/S,DEEP/S,NOCOUNT/S,BUFSIZE/N/K"
  266. Xenum ReadArgs {
  267. X    ARG_FILES,
  268. X    ARG_TO,
  269. X    ARG_ALL,
  270. X    ARG_NOBORD,
  271. X    ARG_XCOMP,
  272. X    ARG_DITHER,
  273. X    ARG_FLIPX,
  274. X    ARG_FLIPY,
  275. X    ARG_DEEP,
  276. X    ARG_NOCOUNT,
  277. X    ARG_BUFSIZ,
  278. X    ARG_sizeof
  279. X};
  280. X
  281. X/* we will make the argument array global so that other modules can get at
  282. X   the ARG_TO, ARG_ALL and ARG_XCOMP fields easily */
  283. Xstruct RDArgs *ArgsPtr;
  284. Xchar *ArgArray[ARG_sizeof];
  285. XBOOL ArgToIsDir;
  286. X
  287. X/* size of the read buffered i/o space */
  288. Xstatic ULONG BufSize = 2048;    /* default size is 2k */
  289. X
  290. Xint NoBorderLineThresh = 0;
  291. X
  292. X/* some mem pointers used when we do dithering */
  293. XBYTE *CurrentLineErr[3];
  294. XBYTE *LastLineErr[3];
  295. X
  296. X/* this flag says if we scaled the image */
  297. XBOOL DidXComp;
  298. X
  299. X/* we print this when the user hits the break key */
  300. Xchar *AbortMsg = "*** User Interruption!\n";
  301. X
  302. X/* storage for our library bases */
  303. Xstruct Library *MathIeeeDoubBasBase = NULL;
  304. Xstruct Library *IFFParseBase = NULL;
  305. Xstruct Library *GfxBase = NULL;
  306. X
  307. X/* storage for our anchor when looking for pattern matches */
  308. Xstruct Anchor {
  309. X        struct AnchorPath APath;
  310. X        char              Path[256];
  311. X    } *anchor = NULL;
  312. X
  313. X/* here we have our main routine */
  314. Xint __regargs main(char *cmdptr, int cmdlen, struct WBStartup *WBMsg)
  315. X{
  316. X    register char **FilesPtr;
  317. X    struct RDArgs MyArgs;
  318. X    extern UBYTE __far arg_help[];
  319. X    extern UBYTE __far VersionID[];
  320. X
  321. X    InitMemory();
  322. X
  323. X    if (WBMsg) {
  324. X        WarnMustUseCLI();
  325. X        MyExit(5);
  326. X    }
  327. X
  328. X    if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37))) {
  329. X        MyPrintf("Unable to access %s!\n", "graphics.library");
  330. X        MyExit(5);
  331. X    }
  332. X
  333. X    if (!(MathIeeeDoubBasBase = OpenLibrary("mathieeedoubbas.library", 0))) {
  334. X        MyPrintf("Unable to access %s!\n", "mathieeedoubbas.library");
  335. X        MyExit(5);
  336. X    }
  337. X
  338. X    if (!(IFFParseBase = OpenLibrary("iffparse.library", 0))) {
  339. X        MyPrintf("Unable to access %s!\n", "iffparse.library");
  340. X        MyExit(5);
  341. X    }
  342. X
  343. X    memset ((char *)&MyArgs, 0, sizeof(struct RDArgs));
  344. X
  345. X    if (!(MyArgs.RDA_ExtHelp = (UBYTE *)MyAlloc(strlen(arg_help) + (2 * strlen(GIFMACH)) + strlen(VersionID) + 1))) {
  346. X        PutStr("Out of memory!\n");
  347. X        MyExit(5);
  348. X    }
  349. X
  350. X    MySPrintf((char *)MyArgs.RDA_ExtHelp, arg_help, GIFMACH, VersionID, GIFMACH);
  351. X
  352. X    if (!(ArgsPtr = ReadArgs(ARG_TEMPLATE, (LONG *)&ArgArray, &MyArgs))) {
  353. X        PrintFault(IoErr(), NULL);
  354. X        MyExit(5);
  355. X    }
  356. X
  357. X    MyFree((char *)MyArgs.RDA_ExtHelp);
  358. X
  359. X    if (ArgArray[ARG_TO])
  360. X        ArgToIsDir = IsDir(ArgArray[ARG_TO]);
  361. X
  362. X    if (ArgArray[ARG_NOBORD]) {
  363. X        NoBorderLineThresh = *((LONG *)ArgArray[ARG_NOBORD]);
  364. X        if (NoBorderLineThresh < 0 || NoBorderLineThresh > 100) {
  365. X            PutStr("Invalid NOBORDER line threshhold specified.\n");
  366. X            MyExit(3);
  367. X        }
  368. X    }
  369. X
  370. X    if (ArgArray[ARG_NOCOUNT])
  371. X        DisplayCounts = FALSE;
  372. X    else
  373. X        DisplayCounts = TRUE;
  374. X        
  375. X    if (ArgArray[ARG_BUFSIZ])
  376. X        BufSize = *((LONG *)ArgArray[ARG_BUFSIZ]) * 1024;
  377. X
  378. X    if (!(FilesPtr = (char **)ArgArray[ARG_FILES])) {
  379. X        PutStr("No GIF files selected.\n");
  380. X        MyExit(3);
  381. X    }
  382. X
  383. X    InitDiff();    /* one time init for the RGBdiff function */
  384. X
  385. X    while (*FilesPtr)
  386. X        DoPattern(*FilesPtr++);
  387. X
  388. X    MyExit(0);
  389. X}
  390. X
  391. Xvoid MyExit(ULONG result)
  392. X{
  393. X    if (GIFfh)
  394. X        Close(GIFfh);
  395. X
  396. X    if (IFFParseBase)
  397. X        CloseLibrary(IFFParseBase);
  398. X
  399. X    if (MathIeeeDoubBasBase)
  400. X        CloseLibrary(MathIeeeDoubBasBase);
  401. X
  402. X    if (GfxBase)
  403. X        CloseLibrary(GfxBase);
  404. X
  405. X    if (anchor)
  406. X        MatchEnd(&anchor->APath);
  407. X
  408. X    if (ArgsPtr)
  409. X        FreeArgs(ArgsPtr);
  410. X
  411. X    FreeAll(1);
  412. X    FreeAll(0);
  413. X
  414. X    XCEXIT(result);
  415. X}
  416. X
  417. X
  418. X/* this will walk through a pattern doing conversions */
  419. Xvoid DoPattern(char *pat)
  420. X{
  421. X    register int error;
  422. X
  423. X    if (!(anchor = (struct Anchor *)MyAlloc(sizeof(struct Anchor)))) {
  424. X        PutStr("Out of memory!\n");
  425. X        MyExit(10);
  426. X    }
  427. X
  428. X    anchor->APath.ap_Strlen = sizeof(anchor->Path);
  429. X    anchor->APath.ap_Flags = APF_DOWILD;
  430. X    anchor->APath.ap_BreakBits = SIGBREAKF_CTRL_C;
  431. X
  432. X    error = MatchFirst(pat, &anchor->APath);
  433. X
  434. X    while (!error) {
  435. X        if (anchor->APath.ap_Info.fib_DirEntryType > 0) {
  436. X            if (ArgArray[ARG_ALL]) {
  437. X                if (!(anchor->APath.ap_Flags & APF_DIDDIR))
  438. X                    anchor->APath.ap_Flags |= APF_DODIR;
  439. X                anchor->APath.ap_Flags &= ~APF_DIDDIR;
  440. X            }
  441. X        } else
  442. X            Convert(anchor->APath.ap_Buf);
  443. X
  444. X        error = MatchNext(&anchor->APath);
  445. X    }
  446. X
  447. X    MatchEnd(&anchor->APath);
  448. X    MyFree((char *)anchor);
  449. X    anchor = NULL;
  450. X
  451. X    switch(error) {
  452. X        case ERROR_BREAK:
  453. X            PutStr(AbortMsg);
  454. X            MyExit(ABORTEXITVAL);
  455. X            break;
  456. X
  457. X        case ERROR_OBJECT_NOT_FOUND:
  458. X            PutStr("File not found.\n");
  459. X            break;
  460. X
  461. X        case ERROR_BUFFER_OVERFLOW:
  462. X            PutStr("Path too long!\n");
  463. X            break;
  464. X
  465. X        case ERROR_NO_MORE_ENTRIES:    /* normal termination */
  466. X            break;
  467. X
  468. X        default:
  469. X            MyPrintf("I/O Error #%ld!\n", error);
  470. X            break;
  471. X    }
  472. X}
  473. X
  474. X/* here we have the routine that gets ready to do the conversion */
  475. Xvoid Convert(char *name)
  476. X{
  477. X    register int index;
  478. X    char *basename;
  479. X    char *ptr;
  480. X    char sig[7];
  481. X    int size;
  482. X    int error;
  483. X    int colours;
  484. X    LONG cmdcode;
  485. X    
  486. X    struct DateStamp StartTime, EndTime;
  487. X
  488. X    CurrentMem++;
  489. X
  490. X    if (!(GIFfh = Open(name, MODE_OLDFILE))) {
  491. X        MyPrintf("Error #%ld trying to open %s...\n", IoErr(), name);
  492. X        goto LeaveConvert;
  493. X    }
  494. X
  495. X    SetVBuf(GIFfh, NULL, BUF_FULL, BufSize);
  496. X
  497. X    sig[6] = NULL;
  498. X
  499. X    if (FRead(GIFfh, sig, 1, 6) != 6 || strncmp("GIF", sig, 3)) {
  500. X        MyPrintf("%s is not a GIF file...\n", name);
  501. X        goto LeaveConvert;
  502. X    }
  503. X
  504. X    MyPrintf("Converting %s ", name);
  505. X
  506. X    basename = FilePart(name);
  507. X    ptr = basename + strlen(basename) - 4;
  508. X
  509. X    if (!strnicmp(".gif", ptr, 4))
  510. X        *ptr = NULL;
  511. X
  512. X    size = strlen(basename) + 6;
  513. X
  514. X    if (ArgArray[ARG_TO]) {
  515. X        if (ArgToIsDir)
  516. X            size += strlen(ArgArray[ARG_TO]) + 1;
  517. X        else
  518. X            size = strlen(ArgArray[ARG_TO]) + 1;
  519. X    }
  520. X
  521. X    if (!(ptr = MyAlloc(size))) {
  522. X        PutStr("... Out of memory!\n");
  523. X        goto LeaveConvert;
  524. X    }
  525. X
  526. X    if (ArgArray[ARG_TO]) {
  527. X        strcpy(ptr, ArgArray[ARG_TO]);
  528. X
  529. X        if (ArgToIsDir) {
  530. X            AddPart(ptr, basename, size);
  531. X            strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
  532. X        }
  533. X    } else {
  534. X        strcpy(ptr, basename);
  535. X        strcat(ptr, (ArgArray[ARG_DEEP] ? ".deep" : ".sham"));
  536. X    }
  537. X
  538. X    MyPrintf("to %s...\n", ptr);
  539. X
  540. X    DateStamp(&StartTime);
  541. X
  542. X    if (FRead(GIFfh, (char *)&gdesc, 1, 7) != 7) {
  543. X        PutStr("Error reading screen descriptor.\n");
  544. X        goto LeaveConvert;
  545. X    }
  546. X
  547. X    FlipWord(&gdesc.gd_Width);
  548. X    FlipWord(&gdesc.gd_Height);
  549. X
  550. X    MyPrintf("Signature = \"%s\", Width = %ld, Height = %ld\n",
  551. X        sig, gdesc.gd_Width, gdesc.gd_Height);
  552. X
  553. X    NewList((struct List *)&CommentList);
  554. X
  555. X    DidXComp = 0;
  556. X    colours = 1L << ((gdesc.gd_ColInfo & 7) + 1);
  557. X
  558. X    if (!(gdesc.gd_ColInfo & 1L << 7)) {
  559. X        PutStr("No global colour map supplied, using internal.\n");
  560. X
  561. X        for (index = 0; index < colours; index++) {
  562. X            GlobalColourTable[index].rgb_Red   =
  563. X            GlobalColourTable[index].rgb_Green =
  564. X            GlobalColourTable[index].rgb_Blue  = index;
  565. X        }
  566. X    } else {
  567. X        MyPrintf("Global colour map contains %ld entries.\n", colours);
  568. X
  569. X        for (index = 0; index < colours; index++) {
  570. X            if (FRead(GIFfh, &GlobalColourTable[index], 1, 3) != 3) {
  571. X                MyPrintf("Error reading global colour #%ld.\n",
  572. X                    index);
  573. X                goto LeaveConvert;
  574. X            }
  575. X        }
  576. X    }
  577. X
  578. X    size = ((gdesc.gd_Width + 7) / 8) + 1;
  579. X    size += (size + 127) >> 7;
  580. X
  581. X    if (!(BitPlane = (struct RGB **)MyAlloc(gdesc.gd_Height * sizeof(struct RGB *))) ||
  582. X        !(SHAMmem  = (UWORD *)MyAlloc(gdesc.gd_Height * 16 * sizeof(UWORD))) ||
  583. X        !(PlaneBuf = (BYTE *)MyAlloc(size))) {
  584. X        PutStr("Out of memory trying to allocate picture.\n");
  585. X        goto LeaveConvert;
  586. X    }
  587. X
  588. X    size = (gdesc.gd_Width + 1) * sizeof(struct RGB);
  589. X
  590. X    for (index = 0; index < gdesc.gd_Height; index++)
  591. X        if (!(BitPlane[index] = (struct RGB *)MyAlloc(size))) {
  592. X            PutStr("Out of memory trying to allocate picture.\n");
  593. X            goto LeaveConvert;
  594. X        }
  595. X
  596. X    size = ((gdesc.gd_Width + 7) / 8) + 1;
  597. X    for (index = 0; index < (ArgArray[ARG_DEEP] ? 24 : 6); index++)
  598. X        if (!(Planes[index] = (UBYTE *)MyAlloc(size))) {
  599. X            PutStr("Out of memory trying to allocate picture.\n");
  600. X            goto LeaveConvert;
  601. X        }
  602. X
  603. X    if (ArgArray[ARG_DITHER]) {
  604. X        size = gdesc.gd_Width * sizeof(BYTE);
  605. X
  606. X        for (index = 0; index < 3; index++)
  607. X            if (!(CurrentLineErr[index] = (BYTE *)MyAlloc(size)) ||
  608. X                !(LastLineErr[index] = (BYTE *)MyAlloc(size))) {
  609. X                PutStr("Out of memory trying to allocate picture.\n");
  610. X                goto LeaveConvert;
  611. X            }
  612. X    }
  613. X
  614. X    ImageNumber = 1;
  615. X
  616. X    /* at this point we start looking for images, extensions or the gif
  617. X       terminator.  we call the appropriate routine as we find each. */
  618. X
  619. X    for (error = FALSE; error == FALSE;) {
  620. X        if ((cmdcode = FGetC(GIFfh)) == -1) {
  621. X            PutStr("...I/O error reading GIF file.\n");
  622. X            goto LeaveConvert;
  623. X        }
  624. X
  625. X        switch(cmdcode) {
  626. X            case GIF_IMAGE:
  627. X                error = DoImage(GIFfh);
  628. X                break;
  629. X
  630. X            case GIF_EXTENSION:
  631. X                error = DoExtension(GIFfh);
  632. X                break;
  633. X
  634. X            case GIF_TERMINATOR:
  635. X                if (ArgArray[ARG_NOBORD])
  636. X                    StripBorder();
  637. X
  638. X                if (ArgArray[ARG_FLIPX])
  639. X                    DoXFlip();
  640. X
  641. X                if (ArgArray[ARG_FLIPY])
  642. X                    DoYFlip();
  643. X
  644. X                if (ArgArray[ARG_XCOMP]) {
  645. X                    DoXComp();
  646. X                    DidXComp = 1;
  647. X                }
  648. X
  649. X                if (gdesc.gd_Height > 200 && DidXComp)
  650. X                    Laced = TRUE;
  651. X                else
  652. X                    Laced = FALSE;
  653. X
  654. X                if (!ArgArray[ARG_DEEP]) {
  655. X                    if (ArgArray[ARG_DITHER])
  656. X                        DitherTo12();
  657. X                    else
  658. X                        ReduceTo12();
  659. X
  660. X                    GIFtoSHAM();
  661. X                }
  662. X
  663. X                error = WriteIFF(ptr, (BOOL)ArgArray[ARG_DEEP]);
  664. X                break;
  665. X
  666. X            default:
  667. X                MyPrintf("...Unknown directive #%ld encountered.\n",
  668. X                    cmdcode);
  669. X                error = TRUE;
  670. X        }
  671. X    }
  672. X
  673. X    DateStamp(&EndTime);
  674. X
  675. X    {
  676. X        register ULONG Hours;
  677. X        register ULONG Minutes;
  678. X        register ULONG Seconds;
  679. X        register ULONG Seconds2;
  680. X    
  681. X        Seconds = (EndTime.ds_Days * 86400) + (EndTime.ds_Minute * 60) + (EndTime.ds_Tick / TICKS_PER_SECOND);
  682. X        Seconds2 = (StartTime.ds_Days * 86400) + (StartTime.ds_Minute * 60) + (StartTime.ds_Tick / TICKS_PER_SECOND);
  683. X
  684. X        Seconds -= Seconds2;
  685. X
  686. X        Hours = Seconds / 3600;
  687. X        Seconds -= Hours * 3600;
  688. X
  689. X        Minutes = Seconds / 60;
  690. X        Seconds -= Minutes * 60;
  691. X
  692. X        MyPrintf("...Conversion time was %ld hour%s, %ld minute%s and %ld second%s.\n",
  693. X            Hours, (Hours != 1 ? "s" : ""),
  694. X            Minutes, (Minutes != 1 ? "s" : ""),
  695. X            Seconds, (Seconds != 1 ? "s" : ""));
  696. X    }
  697. X
  698. XLeaveConvert:
  699. X    FreeAll(CurrentMem--);
  700. X
  701. X    if (GIFfh) {
  702. X        Close(GIFfh);
  703. X        GIFfh = NULL;
  704. X    }
  705. X}
  706. X
  707. X/* this will check to see if we have a directory or not */
  708. XBOOL IsDir(char *name)
  709. X{
  710. X    register BPTR lock;
  711. X    register BOOL result = FALSE;
  712. X
  713. X    struct FileInfoBlock __aligned fib;
  714. X
  715. X    if (lock = Lock(name, ACCESS_READ)) {
  716. X        if (Examine(lock, &fib)) {
  717. X            if (fib.fib_DirEntryType > 0)
  718. X                result = TRUE;
  719. X        }
  720. X        UnLock(lock);
  721. X    }
  722. X
  723. X    return result;
  724. X}
  725. X
  726. X/* this will convert a word from LSB/MSB to MSB/LSB */
  727. Xvoid FlipWord(UWORD *word)
  728. X{
  729. X    register UBYTE swap1;
  730. X    register UBYTE swap2;
  731. X
  732. X    swap1 = *word & 0xFF;
  733. X    swap2 = (*word & 0xFF00) >> 8;
  734. X    *word = swap1 << 8 | swap2;
  735. X}
  736. END_OF_FILE
  737. if test 11230 -ne `wc -c <'Sources/main.c'`; then
  738.     echo shar: \"'Sources/main.c'\" unpacked with wrong size!
  739. fi
  740. # end of 'Sources/main.c'
  741. fi
  742. if test -f 'Sources/writeiff.c' -a "${1}" != "-c" ; then 
  743.   echo shar: Will not clobber existing file \"'Sources/writeiff.c'\"
  744. else
  745. echo shar: Extracting \"'Sources/writeiff.c'\" \(10069 characters\)
  746. sed "s/^X//" >'Sources/writeiff.c' <<'END_OF_FILE'
  747. X/* Copyright 1990 by Christopher A. Wichura.
  748. X   See file GIFMachine.doc for full description of rights.
  749. X*/
  750. X
  751. X#include "GIFMachine.h"
  752. X#include <iff/ILBM.h>
  753. X#include <libraries/iffparse.h>
  754. X#include <graphics/displayinfo.h>
  755. X#include <graphics/view.h>
  756. X#include <dos/datetime.h>
  757. X
  758. X#include <clib/iffparse_protos.h>
  759. Xextern struct Library *IFFParseBase;
  760. X#include <pragmas/iffparse_lib.h>
  761. X
  762. Xextern struct GIFdescriptor gdesc;
  763. XEXTERNBITPLANE;
  764. X
  765. Xextern struct MinList CommentList;
  766. X
  767. Xextern char *AbortMsg;
  768. X
  769. Xextern UWORD *SHAMmem;
  770. XBYTE *PlaneBuf;
  771. X
  772. Xextern BOOL DisplayCounts;
  773. X
  774. XBOOL Laced;
  775. X
  776. XUBYTE *Planes[24];
  777. X
  778. Xstatic UBYTE CompBuf[256];
  779. Xstatic ULONG PlanePos;
  780. X
  781. X/* our version number stuff */
  782. Xextern ULONG __far Version;
  783. Xextern ULONG __far Revision;
  784. X
  785. XBOOL WriteIFF(char *tofile, BOOL DeepFlag)
  786. X{
  787. X    register struct IFFHandle *iff;
  788. X    register int index;
  789. X    register ULONG ChunkSize;
  790. X    register UWORD current;
  791. X    struct DisplayInfo DspInfo;
  792. X    char WrittenBy[40];
  793. X
  794. X    ColorRegister ColourBuf;
  795. X    BitMapHeader  bmh;
  796. X
  797. X    PutStr("...Writing IFF file.");
  798. X
  799. X    if (!GetDisplayInfoData(NULL, (UBYTE *)&DspInfo, sizeof(struct
  800. X        DisplayInfo), DTAG_DISP, (Laced ? HAMLACE_KEY : HAM_KEY))) {
  801. X        PutStr("\n......Error trying to obtain display info.\n");
  802. X        return TRUE;
  803. X    }
  804. X
  805. X    if (!(iff = AllocIFF())) {
  806. X        PutStr("\n......Error allocating IFF handle.\n");
  807. X        return TRUE;
  808. X    }
  809. X
  810. X    if (!(iff->iff_Stream = Open(tofile, MODE_NEWFILE))) {
  811. X        MyPrintf("\n......Error %ld trying to create %s.", IoErr(), tofile);
  812. X        goto EndWriteIFF;
  813. X    }
  814. X
  815. X    InitIFFasDOS(iff);
  816. X
  817. X    if (OpenIFF(iff, IFFF_WRITE)) {
  818. X        PutStr("\n......Error writing to IFF.\n");
  819. X        goto EndWriteIFF;
  820. X    }
  821. X
  822. X    if (PushChunk(iff, ID_ILBM, ID_FORM, IFFSIZE_UNKNOWN)) {
  823. X        PutStr("\n......Error writing to IFF.\n");
  824. X        goto EndWriteIFF;
  825. X    }
  826. X
  827. X    if (PushChunk(iff, 0L, MAKE_ID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
  828. X        PutStr("\n......Error writing to IFF.\n");
  829. X        goto EndWriteIFF;
  830. X    }
  831. X
  832. X    MySPrintf(WrittenBy, "Written by GIFMachine v%ld.%ld on ", Version, Revision);
  833. X
  834. X    if (WriteChunkBytes(iff, (APTR)&WrittenBy, strlen(WrittenBy)) != strlen(WrittenBy)) {
  835. X        PutStr("\n......Error writing to IFF.\n");
  836. X        goto EndWriteIFF;
  837. X    }
  838. X
  839. X    {
  840. X        struct DateTime dat;
  841. X        char Date[LEN_DATSTRING + 1];
  842. X        int DateLength;
  843. X
  844. X        DateStamp(&dat.dat_Stamp);
  845. X        dat.dat_Format = FORMAT_DOS;
  846. X        dat.dat_Flags = 0;
  847. X        dat.dat_StrDay = NULL;
  848. X        dat.dat_StrDate = Date;
  849. X        dat.dat_StrTime = NULL;
  850. X
  851. X        memset(Date, 0, LEN_DATSTRING + 1);
  852. X        DateToStr(&dat);
  853. X
  854. X        DateLength = strlen(Date) + 1;
  855. X        if (WriteChunkBytes(iff, (APTR)&Date, DateLength) != DateLength) {
  856. X            PutStr("\n......Error writing to IFF.\n");
  857. X            goto EndWriteIFF;
  858. X        }
  859. X    }
  860. X
  861. X    if (PopChunk(iff)) {
  862. X        PutStr("\n......Error writing to IFF.\n");
  863. X        goto EndWriteIFF;
  864. X    }
  865. X
  866. X    {
  867. X        struct CommentNode *cn;
  868. X        char ANNObuf[1];
  869. X
  870. X#define C_BLOCK_ID "GIF Comment Block: "
  871. X
  872. X        ANNObuf[0] = 0;
  873. X
  874. X        while (cn = (struct CommentNode *)RemHead((struct List *)&CommentList)) {
  875. X            if (PushChunk(iff, 0L, MAKE_ID('A','N','N','O'), IFFSIZE_UNKNOWN)) {
  876. X                PutStr("\n......Error writing to IFF.\n");
  877. X                goto EndWriteIFF;
  878. X            }
  879. X
  880. X            if (WriteChunkBytes(iff, (APTR)C_BLOCK_ID, strlen(C_BLOCK_ID)) != strlen(C_BLOCK_ID)) {
  881. X                PutStr("\n......Error writing to IFF.\n");
  882. X                goto EndWriteIFF;
  883. X            }
  884. X
  885. X            if (WriteChunkBytes(iff, (APTR)cn->cn_Comment, cn->cn_CommentLength) != cn->cn_CommentLength) {
  886. X                PutStr("\n......Error writing to IFF.\n");
  887. X                goto EndWriteIFF;
  888. X            }
  889. X
  890. X            if (WriteChunkBytes(iff, (APTR)ANNObuf, 1) != 1) {
  891. X                PutStr("\n......Error writing to IFF.\n");
  892. X                goto EndWriteIFF;
  893. X            }
  894. X
  895. X            if (PopChunk(iff)) {
  896. X                PutStr("\n......Error writing to IFF.\n");
  897. X                goto EndWriteIFF;
  898. X            }
  899. X        }
  900. X    }
  901. X
  902. X    if (PushChunk(iff, 0L, ID_BMHD, sizeof(BitMapHeader))) {
  903. X        PutStr("\n......Error writing to IFF.\n");
  904. X        goto EndWriteIFF;
  905. X    }
  906. X
  907. X    bmh.w                 = (gdesc.gd_Width & 1) ? gdesc.gd_Width + 1 : gdesc.gd_Width;
  908. X    bmh.h                 = (gdesc.gd_Height & 1) ? gdesc.gd_Height + 1 : gdesc.gd_Height;
  909. X    bmh.x       = bmh.y  = 0;
  910. X    bmh.nPlanes          = (DeepFlag ? 24 : 6);
  911. X    bmh.masking          = mskNone;
  912. X    bmh.compression      = cmpByteRun1;
  913. X    bmh.pad1             = 0;
  914. X    bmh.transparentColor = 0;
  915. X    bmh.xAspect          = DspInfo.Resolution.x;
  916. X    bmh.yAspect          = DspInfo.Resolution.y;
  917. X    bmh.pageWidth        = 320;
  918. X    bmh.pageHeight       = (Laced ? 400 : 200);
  919. X
  920. X    if (WriteChunkBytes(iff, (APTR)&bmh, sizeof(BitMapHeader)) != sizeof(BitMapHeader)) {
  921. X        PutStr("\n......Error writing to IFF.\n");
  922. X        goto EndWriteIFF;
  923. X    }
  924. X
  925. X    if (PopChunk(iff)) {
  926. X        PutStr("\n......Error writing to IFF.\n");
  927. X        goto EndWriteIFF;
  928. X    }
  929. X
  930. X    if (PushChunk(iff, 0L, ID_CAMG, 4)) {
  931. X        PutStr("\n......Error writing to IFF.\n");
  932. X        goto EndWriteIFF;
  933. X    }
  934. X
  935. X    {
  936. X        LONG CAMGbuf[1];
  937. X
  938. X        CAMGbuf[0] = (DeepFlag ? 0 : HAM) | (Laced ? LACE : 0);
  939. X
  940. X        if (WriteChunkBytes(iff, (APTR)&CAMGbuf, 4) != 4) {
  941. X            PutStr("\n......Error writing to IFF.\n");
  942. X            goto EndWriteIFF;
  943. X        }
  944. X    }
  945. X
  946. X    if (PopChunk(iff)) {
  947. X        PutStr("\n......Error writing to IFF.\n");
  948. X        goto EndWriteIFF;
  949. X    }
  950. X
  951. X    if (!DeepFlag) {
  952. X        if (PushChunk(iff, 0L, ID_CMAP, 16 * 3)) {
  953. X            PutStr("\n......Error writing to IFF.\n");
  954. X            goto EndWriteIFF;
  955. X        }
  956. X
  957. X        for (index = 0; index < 16; index++) {
  958. X            current = SHAMmem[index];
  959. X
  960. X            ColourBuf.red   = (current >> 4) & 0xF0;
  961. X            ColourBuf.green = current & 0xF0;
  962. X            ColourBuf.blue  = (current & 15) << 4;
  963. X
  964. X            if (WriteChunkBytes(iff, (APTR)&ColourBuf, sizeofColorRegister) != sizeofColorRegister) {
  965. X                PutStr("\n......Error writing to IFF.\n");
  966. X                goto EndWriteIFF;
  967. X            }
  968. X        }
  969. X
  970. X        if (PopChunk(iff)) {
  971. X            PutStr("\n......Error writing to IFF.\n");
  972. X            goto EndWriteIFF;
  973. X        }
  974. X
  975. X        ChunkSize = (Laced ? gdesc.gd_Height / 2 : gdesc.gd_Height) * 16 * sizeof(UWORD);
  976. X
  977. X        if (PushChunk(iff, 0L, MAKE_ID('S','H','A','M'), IFFSIZE_UNKNOWN)) {
  978. X            PutStr("\n......Error writing to IFF.\n");
  979. X            goto EndWriteIFF;
  980. X        }
  981. X
  982. X        {
  983. X            UWORD SHAMversion[1];
  984. X
  985. X            SHAMversion[0] = 0;
  986. X
  987. X            if (WriteChunkBytes(iff, (APTR)&SHAMversion, sizeof(UWORD)) != sizeof(UWORD)) {
  988. X                PutStr("\n......Error writing to IFF.\n");
  989. X                goto EndWriteIFF;
  990. X            }
  991. X        }
  992. X
  993. X        if (WriteChunkBytes(iff, (APTR)SHAMmem, ChunkSize) != ChunkSize) {
  994. X            PutStr("\n......Error writing to IFF.\n");
  995. X            goto EndWriteIFF;
  996. X        }
  997. X
  998. X        if (gdesc.gd_Height & 1) {
  999. X            UWORD BlankSHAM[16];
  1000. X
  1001. X            memset((char *)BlankSHAM, 0, sizeof(BlankSHAM));
  1002. X
  1003. X            if (WriteChunkBytes(iff, (APTR)BlankSHAM, sizeof(BlankSHAM)) != sizeof(BlankSHAM)) {
  1004. X                PutStr("\n......Error writing to IFF.\n");
  1005. X                goto EndWriteIFF;
  1006. X            }
  1007. X        }
  1008. X
  1009. X        if (PopChunk(iff)) {
  1010. X            PutStr("\n......Error writing to IFF.\n");
  1011. X            goto EndWriteIFF;
  1012. X        }
  1013. X    } /* end if (!DeepFlag) */
  1014. X
  1015. X    if (PushChunk(iff, 0L, ID_BODY, IFFSIZE_UNKNOWN)) {
  1016. X        PutStr("\n......Error writing to IFF.\n");
  1017. X        goto EndWriteIFF;
  1018. X    }
  1019. X
  1020. X    /* now we actually write the body chunk out */
  1021. X    {
  1022. X        register int plane;
  1023. X        register int col;
  1024. X        register UWORD x;
  1025. X        register UWORD y;
  1026. X        register int index;
  1027. X        UBYTE PlaneMask, ColMask;
  1028. X        UWORD Cols;
  1029. X
  1030. X        if (DisplayCounts)
  1031. X            PutStr("\n......Line ");
  1032. X        else
  1033. X            PutStr("\n......Working");
  1034. X        Flush(Output());
  1035. X
  1036. X        Cols = (bmh.w + 7) / 8;
  1037. X        if (IS_ODD(Cols))
  1038. X            Cols++;
  1039. X
  1040. X        for (y = 0; y < ((gdesc.gd_Height & 1) ? gdesc.gd_Height + 1 : gdesc.gd_Height) ; y++) {
  1041. X            if (DisplayCounts)
  1042. X                MyPrintf("%5ld", y);
  1043. X
  1044. X            if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) {
  1045. X                MyPrintf("\n%s", AbortMsg);
  1046. X                CloseIFF(iff);
  1047. X                Close(iff->iff_Stream);
  1048. X                FreeIFF(iff);
  1049. X                MyExit(ABORTEXITVAL);
  1050. X            }
  1051. X
  1052. X            if (y != gdesc.gd_Height)
  1053. X                for (index = 0; index < (DeepFlag ? 3 : 1); index++) {
  1054. X                    col = 0;
  1055. X                    ColMask = 1L << 7;
  1056. X
  1057. X                    for (x = 0; x < gdesc.gd_Width; x++) {
  1058. X                        if (DeepFlag)
  1059. X                            current = *((UBYTE *)&BitPlane[y][x]+index);
  1060. X                        else
  1061. X                            current = GetValue(x, y);
  1062. X
  1063. X                        PlaneMask = 1;
  1064. X                        for (plane = 0; plane < (DeepFlag ? 8 : 6); plane++) {
  1065. X                            if (current & PlaneMask)
  1066. X                                Planes[plane + index * 8][col] |= ColMask;
  1067. X
  1068. X                            PlaneMask <<= 1;
  1069. X                        }
  1070. X
  1071. X                        if (ColMask == 1) {
  1072. X                            ColMask = 1L << 7;
  1073. X                            col++;
  1074. X                        } else
  1075. X                            ColMask >>= 1;
  1076. X                    }
  1077. X                }
  1078. X
  1079. X            /* now we need to compress the scan line */
  1080. X
  1081. X            {
  1082. X                register BOOL state;
  1083. X                register char c;
  1084. X                register char lastc;
  1085. X                register UWORD nbuf;
  1086. X                register UWORD rstart;
  1087. X
  1088. X                for (plane = 0; plane < (DeepFlag ? 24 : 6); plane++) {
  1089. X
  1090. X                    CompBuf[0] = lastc = c = Planes[plane][0];
  1091. X
  1092. X                    state = FALSE;
  1093. X                    PlanePos = rstart = 0;
  1094. X                    nbuf = col = 1;
  1095. X
  1096. X                    while (col < Cols) {
  1097. X                        CompBuf[nbuf++] = c = Planes[plane][col++];
  1098. X
  1099. X                        switch (state) {
  1100. X                            case FALSE:
  1101. X                            if (nbuf > 128) {
  1102. X                                OutDump(nbuf - 1);
  1103. X                                CompBuf[0] = c;
  1104. X                                nbuf = 1;
  1105. X                                rstart = 0;
  1106. X                                break;
  1107. X                            }
  1108. X
  1109. X                            if (c == lastc) {
  1110. X                                if (nbuf - rstart >= 3) {
  1111. X                                    if (rstart > 0)
  1112. X                                            OutDump(rstart);
  1113. X                                    state = TRUE;
  1114. X                                } else if (rstart == 0)
  1115. X                                    state = TRUE;
  1116. X                            } else
  1117. X                                rstart = nbuf - 1;
  1118. X
  1119. X                            break;
  1120. X
  1121. X                            case TRUE:
  1122. X                            if ((c != lastc) || (nbuf - rstart > 128)) {
  1123. X                                OutRun(nbuf - 1 - rstart, lastc);
  1124. X                                CompBuf[0] = c;
  1125. X                                nbuf = 1;
  1126. X                                rstart = 0;
  1127. X                                state = FALSE;
  1128. X                            }
  1129. X
  1130. X                            break;
  1131. X                        }
  1132. X
  1133. X                        lastc = c;
  1134. X                    }
  1135. X
  1136. X                    switch (state) {
  1137. X                        case FALSE:
  1138. X                        OutDump(nbuf);
  1139. X                        break;
  1140. X
  1141. X                        case TRUE:
  1142. X                        OutRun(nbuf - rstart, lastc);
  1143. X                        break;
  1144. X                    }
  1145. X
  1146. X                    /* now write the compressed plane out */
  1147. X                    if (WriteChunkBytes(iff, (APTR)PlaneBuf, PlanePos) != PlanePos) {
  1148. X                        PutStr("\n......Error writing to IFF.\n");
  1149. X                        goto EndWriteIFF;
  1150. X                    }
  1151. X
  1152. X                    memset((char *)Planes[plane], 0, Cols);
  1153. X                }
  1154. X            }
  1155. X
  1156. X            if (DisplayCounts)
  1157. X                MyPrintf("\x1B[5D");
  1158. X        }
  1159. X
  1160. X    }
  1161. X
  1162. X    if (PopChunk(iff)) {
  1163. X        PutStr("\n......Error writing to IFF.\n");
  1164. X        goto EndWriteIFF;
  1165. X    }
  1166. X
  1167. X    if (PopChunk(iff)) {
  1168. X        PutStr("\n......Error writing to IFF.\n");
  1169. X        goto EndWriteIFF;
  1170. X    }
  1171. X
  1172. X    MyPrintf("\x1B[%ldD\x1B[KWritten.\n", (DisplayCounts ? 5 : 7));
  1173. X
  1174. XEndWriteIFF:
  1175. X    CloseIFF(iff);
  1176. X    if (iff->iff_Stream)
  1177. X        Close(iff->iff_Stream);
  1178. X    FreeIFF(iff);
  1179. X
  1180. X    return TRUE;
  1181. X}
  1182. X
  1183. Xvoid OutDump(int nn)
  1184. X{
  1185. X    register int index;
  1186. X
  1187. X    PlaneBuf[PlanePos++] = nn - 1;
  1188. X
  1189. X    for (index = 0; index < nn; index++)
  1190. X        PlaneBuf[PlanePos++] = CompBuf[index];
  1191. X}
  1192. X
  1193. Xvoid OutRun(int nn, int cc)
  1194. X{
  1195. X    PlaneBuf[PlanePos++] = -(nn - 1);
  1196. X    PlaneBuf[PlanePos++] = cc;
  1197. X}
  1198. END_OF_FILE
  1199. if test 10069 -ne `wc -c <'Sources/writeiff.c'`; then
  1200.     echo shar: \"'Sources/writeiff.c'\" unpacked with wrong size!
  1201. fi
  1202. # end of 'Sources/writeiff.c'
  1203. fi
  1204. echo shar: End of archive 2 \(of 3\).
  1205. cp /dev/null ark2isdone
  1206. MISSING=""
  1207. for I in 1 2 3 ; do
  1208.     if test ! -f ark${I}isdone ; then
  1209.     MISSING="${MISSING} ${I}"
  1210.     fi
  1211. done
  1212. if test "${MISSING}" = "" ; then
  1213.     echo You have unpacked all 3 archives.
  1214.     rm -f ark[1-9]isdone
  1215. else
  1216.     echo You still need to unpack the following archives:
  1217.     echo "        " ${MISSING}
  1218. fi
  1219. ##  End of shell archive.
  1220. exit 0
  1221. -- 
  1222. Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
  1223. Mail comments to the moderator at <amiga-request@uunet.uu.net>.
  1224. Post requests for sources, and general discussion to comp.sys.amiga.misc.
  1225.